home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HPAVC
/
HPAVC CD-ROM.iso
/
MCASM.RAR
/
MC_ASM.EXE
/
WROX_ASM
/
CH12
/
COMMON
/
MAPPER2.H
< prev
next >
Wrap
C/C++ Source or Header
|
1994-09-24
|
6KB
|
139 lines
#ifndef mapper2_h
#define mapper2_h
#include "palette.h"
#include "mapper.h"
/*
* Map a TrueColor image into given palette
* Big part of code and ideas were taken
* from the Independent JPEG Group's software.
* ( see the accompanying README file).
* E.Podvoysky from ^Z for WROX press book
*/
/* see palette.h - first part of task */
/* E.P. - I do not re-use histogram space, because I split class.
* so in mapper cache we may have 1-byte cells
* (but using only 255 colors, not 256.)
*
* We re-use the histogram space as an "inverse color map", essentially a
* cache for the results of nearest-color searches. All colors within a
* histogram cell will be mapped to the same colormap entry, namely the one
* closest to the cell's center. This may not be quite the closest entry to
* the actual input color, but it's almost as good. A zero in the cache
* indicates we haven't found the nearest color for that cell yet; the array
* is cleared to zeroes before starting the mapping pass. When we find the
* nearest color for a cell, its colormap index plus one is recorded in the
* cache for future use. The pass2 scanning routines call fill_inverse_cmap
* when they need to use an unfilled entry in the cache.
*
* Our method of efficiently finding nearest colors is based on the "locally
* sorted search" idea described by Heckbert and on the incremental distance
* calculation described by Spencer W. Thomas in chapter III.1 of Graphics
* Gems II (James Arvo, ed. Academic Press, 1991). Thomas points out that
* the distances from a given colormap entry to each cell of the histogram can
* be computed quickly using an incremental method: the differences between
* distances to adjacent cells themselves differ by a constant. This allows a
* fairly fast implementation of the "brute force" approach of computing the
* distance from every colormap entry to every histogram cell. Unfortunately,
* it needs a work array to hold the best-distance-so-far for each histogram
* cell (because the inner loop has to be over cells, not colormap entries).
* The work array elements have to be INT32s, so the work array would need
* 256Kb at our recommended precision. This is not feasible in DOS machines.
* Another disadvantage of the brute force approach is that it computes
* distances to every cell of the cubical histogram. When working with YCbCr
* input, only about a quarter of the cube represents realizable colors, so
* many of the cells will never be used and filling them is wasted effort.
*
* To get around these problems, we apply Thomas' method to compute the
* nearest colors for only the cells within a small subbox of the histogram.
* The work array need be only as big as the subbox, so the memory usage
* problem is solved. A subbox is processed only when some cell in it is
* referenced by the pass2 routines, so we will never bother with cells far
* outside the realizable color volume. An additional advantage of this
* approach is that we can apply Heckbert's locality criterion to quickly
* eliminate colormap entries that are far away from the subbox; typically
* three-fourths of the colormap entries are rejected by Heckbert's criterion,
* and we need not compute their distances to individual cells in the subbox.
* The speed of this approach is heavily influenced by the subbox size: too
* small means too much overhead, too big loses because Heckbert's criterion
* can't eliminate as many colormap entries. Empirically the best subbox
* size seems to be about 1/512th of the histogram (1/8th in each direction).
*
* Thomas' article also describes a refined method which is asymptotically
* faster than the brute-force method, but it is also far more complex and
* cannot efficiently be applied to small subboxes. It is therefore not
* useful for programs intended to be portable to DOS machines. On machines
* with plenty of memory, filling the whole histogram in one shot with Thomas'
* refined method might be faster than the present code --- but then again,
* it might not be any faster, and it's certainly more complicated.
*/
#define MAP_R_BITS HIST_R_BITS /* bits of precision in R map */
#define MAP_G_BITS HIST_G_BITS /* bits of precision in G map */
#define MAP_B_BITS HIST_B_BITS /* bits of precision in B map */
#define MAP_G_ELEMS (1<<MAP_G_BITS) /* # of elements along histogram axes */
#define MAP_R_ELEMS (1<<MAP_R_BITS)
#define MAP_B_ELEMS (1<<MAP_B_BITS)
#define MAP_G_SHIFT (8 - MAP_G_BITS)
#define MAP_R_SHIFT (8 - MAP_R_BITS)
#define MAP_B_SHIFT (8 - MAP_B_BITS)
#define BOX_R_LOG (MAP_R_BITS-3) /* log2(map cells in update box, R axes) */
#define BOX_G_LOG (MAP_G_BITS-3) /* log2(map cells in update box, G axes) */
#define BOX_B_LOG (MAP_B_BITS-3) /* log2(map cells in update box, C axes) */
#define BOX_R_ELEMS (1<<BOX_R_LOG) /* # of map cells in update box */
#define BOX_G_ELEMS (1<<BOX_G_LOG)
#define BOX_B_ELEMS (1<<BOX_B_LOG)
#define BOX_R_SHIFT (R_SHIFT + BOX_R_LOG)
#define BOX_G_SHIFT (G_SHIFT + BOX_G_LOG)
#define BOX_B_SHIFT (B_SHIFT + BOX_B_LOG)
#ifdef INT_MAP_CELL
typedef int mapcell; /* color map cell */
#else
typedef BYTE mapcell; /* color map cell */
#endif
typedef mapcell far *mapptr; /* for pointers to map cells */
typedef mapcell map1d[MAP_B_ELEMS]; /* typedefs for the array */
typedef map1d far * map2d; /* type for the R-level pointers */
typedef map2d *map3d; /* typedefs for the array */
// no dithering, pre-selected colors
class color_mapper_palette : public color_mapper {
protected:
int map_r_elements; // internal use
// map3d map; /* pointer to the map */
mapptr *map;
int find_nearby_colors (int minc0, int minc1, int minc2,BYTE colorlist[]);
void find_best_colors (int minc0, int minc1, int minc2,
int numcolors, BYTE colorlist[], BYTE bestcolor[]);
void fill_inverse_cmap (int c0, int c1, int c2);
virtual int initmap();
public:
color_mapper_palette(int colors_,int width_,BGRpalette colormap);
virtual ~color_mapper_palette();
virtual void process_line (BYTE *R, BYTE *G, BYTE *B, BYTE *out_line);
};
class color_mapper_palette_dith : public color_mapper_palette {
public:
color_mapper_palette_dith(int colors_,int width_,BGRpalette colormap);
virtual void process_line(BYTE *R, BYTE *G, BYTE *B, BYTE *out_line);
};
#endif